home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / comms / non-internet / samba / source / ipc.c < prev    next >
C/C++ Source or Header  |  1996-06-26  |  71KB  |  2,669 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    Inter-process communication and named pipe handling
  5.    Copyright (C) Andrew Tridgell 1992-1995
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.    */
  21. /*
  22.    This file handles the named pipe and mailslot calls
  23.    in the SMBtrans protocol
  24.    */
  25.  
  26. #include "includes.h"
  27. #include "loadparm.h"
  28. #include "pcap.h"
  29.  
  30. #ifdef CHECK_TYPES
  31. #undef CHECK_TYPES
  32. #endif
  33. #define CHECK_TYPES 0
  34.  
  35. extern int DEBUGLEVEL;
  36. extern int maxxmit;
  37. extern files_struct Files[];
  38.  
  39. extern fstring local_machine;
  40.  
  41. #define NERR_Success 0
  42. #define NERR_badpass 86
  43. #define NERR_notsupported 50
  44.  
  45. #define NERR_BASE (2100)
  46. #define NERR_BufTooSmall (NERR_BASE+23)
  47. #define NERR_JobNotFound (NERR_BASE+51)
  48. #define NERR_DestNotFound (NERR_BASE+52)
  49. #define ERROR_INVALID_LEVEL 124
  50. #define ERROR_MORE_DATA 234
  51.  
  52. #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
  53.  
  54. #define ACCESS_READ 0x01
  55. #define ACCESS_WRITE 0x02
  56. #define ACCESS_CREATE 0x04
  57.  
  58. #define SHPWLEN 8        /* share password length */
  59. #define NNLEN 12        /* 8.3 net name length */
  60. #define SNLEN 15        /* service name length */
  61. #define QNLEN 12        /* queue name maximum length */
  62.  
  63. extern int Client;
  64.  
  65. static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
  66. {
  67.   pstring buf;
  68.   int l;
  69.  
  70.   if (!src || !dst || !n || !(*dst)) return(0);
  71.  
  72.   StrnCpy(buf,src,sizeof(buf)/2);
  73.   string_sub(buf,"%S",lp_servicename(snum));
  74.   standard_sub(cnum,buf);
  75.   StrnCpy(*dst,buf,*n);
  76.   l = strlen(*dst) + 1;
  77.   (*dst) += l;
  78.   (*n) -= l;
  79.   return l;
  80. }
  81.  
  82. static int CopyAndAdvance(char** dst, char* src, int* n)
  83. {
  84.   int l;
  85.   if (!src || !dst || !n || !(*dst)) return(0);
  86.   StrnCpy(*dst,src,*n);
  87.   l = strlen(*dst) + 1;
  88.   (*dst) += l;
  89.   (*n) -= l;
  90.   return l;
  91. }
  92.  
  93. static int StrlenExpanded(int cnum, int snum, char* s)
  94. {
  95.   pstring buf;
  96.   if (!s) return(0);
  97.   StrnCpy(buf,s,sizeof(buf)/2);
  98.   string_sub(buf,"%S",lp_servicename(snum));
  99.   standard_sub(cnum,buf);
  100.   return strlen(buf) + 1;
  101. }
  102.  
  103. static char* Expand(int cnum, int snum, char* s)
  104. {
  105.   static pstring buf;
  106.   if (!s) return(NULL);
  107.   StrnCpy(buf,s,sizeof(buf)/2);
  108.   string_sub(buf,"%S",lp_servicename(snum));
  109.   standard_sub(cnum,buf);
  110.   return &buf[0];
  111. }
  112.  
  113. /*******************************************************************
  114.   check a API string for validity when we only need to check the prefix
  115.   ******************************************************************/
  116. static BOOL prefix_ok(char *str,char *prefix)
  117. {
  118.   return(strncmp(str,prefix,strlen(prefix)) == 0);
  119. }
  120.  
  121.  
  122. /****************************************************************************
  123.   send a trans reply
  124.   ****************************************************************************/
  125. static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
  126.                  int ldata,int lparam,int lsetup)
  127. {
  128.   int i;
  129.   int this_ldata,this_lparam;
  130.   int tot_data=0,tot_param=0;
  131.   int align;
  132.  
  133.   this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */
  134.   this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam));
  135.  
  136.   align = (this_lparam%4);
  137.  
  138.   set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
  139.   if (this_lparam)
  140.     memcpy(smb_buf(outbuf),param,this_lparam);
  141.   if (this_ldata)
  142.     memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
  143.  
  144.   SSVAL(outbuf,smb_vwv0,lparam);
  145.   SSVAL(outbuf,smb_vwv1,ldata);
  146.   SSVAL(outbuf,smb_vwv3,this_lparam);
  147.   SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
  148.   SSVAL(outbuf,smb_vwv5,0);
  149.   SSVAL(outbuf,smb_vwv6,this_ldata);
  150.   SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
  151.   SSVAL(outbuf,smb_vwv8,0);
  152.   SSVAL(outbuf,smb_vwv9,lsetup);
  153.   for (i=0;i<lsetup;i++)
  154.     SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
  155.  
  156.   show_msg(outbuf);
  157.   send_smb(Client,outbuf);
  158.  
  159.   tot_data = this_ldata;
  160.   tot_param = this_lparam;
  161.  
  162.   while (tot_data < ldata || tot_param < lparam)
  163.     {
  164.       this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
  165.       this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam));
  166.  
  167.       align = (this_lparam%4);
  168.  
  169.       set_message(outbuf,10,this_ldata+this_lparam+align,False);
  170.       if (this_lparam)
  171.     memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
  172.       if (this_ldata)
  173.     memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
  174.  
  175.       SSVAL(outbuf,smb_vwv3,this_lparam);
  176.       SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
  177.       SSVAL(outbuf,smb_vwv5,tot_param);
  178.       SSVAL(outbuf,smb_vwv6,this_ldata);
  179.       SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
  180.       SSVAL(outbuf,smb_vwv8,tot_data);
  181.       SSVAL(outbuf,smb_vwv9,0);
  182.  
  183.       show_msg(outbuf);
  184.       send_smb(Client,outbuf);
  185.  
  186.       tot_data += this_ldata;
  187.       tot_param += this_lparam;
  188.     }
  189. }
  190.  
  191.  
  192.  
  193. /****************************************************************************
  194.   get a print queue
  195.   ****************************************************************************/
  196.  
  197. struct pack_desc {
  198.   char* format;        /* formatstring for structure */
  199.   char* subformat;  /* subformat for structure */
  200.   char* base;        /* baseaddress of buffer */
  201.   int buflen;       /* remaining size for fixed part; on init: length of base */
  202.   int subcount;        /* count of substructures */
  203.   char* structbuf;  /* pointer into buffer for remaining fixed part */
  204.   int stringlen;    /* remaining size for variable part */        
  205.   char* stringbuf;  /* pointer into buffer for remaining variable part */
  206.   int neededlen;    /* total needed size */
  207.   int usedlen;        /* total used size (usedlen <= neededlen and usedlen <= buflen) */
  208.   char* curpos;        /* current position; pointer into format or subformat */
  209.   int errcode;
  210. };
  211.  
  212. static int get_counter(char** p)
  213. {
  214.   int i, n;
  215.   if (!p || !(*p)) return(1);
  216.   if (!isdigit(**p)) return 1;
  217.   for (n = 0;;) {
  218.     i = **p;
  219.     if (isdigit(i))
  220.       n = 10 * n + (i - '0');
  221.     else
  222.       return n;
  223.     (*p)++;
  224.   }
  225. }
  226.  
  227. static int getlen(char* p)
  228. {
  229.   int n = 0;
  230.   if (!p) return(0);
  231.   while (*p) {
  232.     switch( *p++ ) {
  233.     case 'W':            /* word (2 byte) */
  234.       n += 2;
  235.       break;
  236.     case 'N':            /* count of substructures (word) at end */
  237.       n += 2;
  238.       break;
  239.     case 'D':            /* double word (4 byte) */
  240.     case 'z':            /* offset to zero terminated string (4 byte) */
  241.     case 'l':            /* offset to user data (4 byte) */
  242.       n += 4;
  243.       break;
  244.     case 'b':            /* offset to data (with counter) (4 byte) */
  245.       n += 4;
  246.       get_counter(&p);
  247.       break;
  248.     case 'B':            /* byte (with optional counter) */
  249.       n += get_counter(&p);
  250.       break;
  251.     }
  252.   }
  253.   return n;
  254. }
  255.  
  256. static BOOL init_package(struct pack_desc* p, int count, int subcount)
  257. {
  258.   int n = p->buflen;
  259.   int i;
  260.  
  261.   if (!p->format || !p->base) return(False);
  262.  
  263.   i = count * getlen(p->format);
  264.   if (p->subformat) i += subcount * getlen(p->subformat);
  265.   p->structbuf = p->base;
  266.   p->neededlen = 0;
  267.   p->usedlen = 0;
  268.   p->subcount = 0;
  269.   p->curpos = p->format;
  270.   if (i > n) {
  271.     i = n = 0;
  272.     p->errcode = NERR_BufTooSmall;
  273.   }
  274.  
  275.   p->errcode = NERR_Success;
  276.   p->buflen = i;
  277.   n -= i;
  278.   p->stringbuf = p->base + i;
  279.   p->stringlen = n;
  280.   return(p->errcode == NERR_Success);
  281. }
  282.  
  283. #ifdef __STDC__
  284. static int package(struct pack_desc* p, ...)
  285. {
  286. #else
  287. static int package(va_alist)
  288. va_dcl
  289. {
  290.   struct pack_desc* p;
  291. #endif
  292.   va_list args;
  293.   int needed=0, stringneeded;
  294.   char* str=NULL;
  295.   int is_string=0, stringused;
  296.   int32 temp;
  297.  
  298. #ifdef __STDC__
  299.   va_start(args,p);
  300. #else
  301.   va_start(args);
  302.   p = va_arg(args,struct pack_desc *);
  303. #endif
  304.  
  305.   if (!*p->curpos) {
  306.     if (!p->subcount)
  307.       p->curpos = p->format;
  308.     else {
  309.       p->curpos = p->subformat;
  310.       p->subcount--;
  311.     }
  312.   }
  313. #if CHECK_TYPES
  314.   str = va_arg(args,char*);
  315.   if (strncmp(str,p->curpos,strlen(str)) != 0) {
  316.     DEBUG(2,("type error in package: %s instead of %*s\n",str,
  317.           strlen(str),p->curpos));
  318.     va_end(args);
  319. #if AJT
  320.     ajt_panic();
  321. #endif  
  322.     return 0;
  323.   }
  324. #endif
  325.   stringneeded = -1;
  326.  
  327.   if (!p->curpos) return(0);
  328.  
  329.   switch( *p->curpos++ ) {
  330.   case 'W':            /* word (2 byte) */
  331.     needed = 2;
  332.     temp = va_arg(args,int);
  333.     if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
  334.     break;
  335.   case 'N':            /* count of substructures (word) at end */
  336.     needed = 2;
  337.     p->subcount = va_arg(args,int);
  338.     if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
  339.     break;
  340.   case 'D':            /* double word (4 byte) */
  341.     needed = 4;
  342.     temp = va_arg(args,int);
  343.     if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
  344.     break;
  345.   case 'B':            /* byte (with optional counter) */
  346.     needed = get_counter(&p->curpos);
  347.     {
  348.       char *s = va_arg(args,char*);
  349.       if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
  350.     }
  351.     break;
  352.   case 'z':            /* offset to zero terminated string (4 byte) */
  353.     str = va_arg(args,char*);
  354.     stringneeded = (str ? strlen(str)+1 : 0);
  355.     is_string = 1;
  356.     break;
  357.   case 'l':            /* offset to user data (4 byte) */
  358.     str = va_arg(args,char*);
  359.     stringneeded = va_arg(args,int);
  360.     is_string = 0;
  361.     break;
  362.   case 'b':            /* offset to data (with counter) (4 byte) */
  363.     str = va_arg(args,char*);
  364.     stringneeded = get_counter(&p->curpos);
  365.     is_string = 0;
  366.     break;
  367.   }
  368.   va_end(args);
  369.   if (stringneeded >= 0) {
  370.     needed = 4;
  371.     if (p->buflen >= needed) {
  372.       stringused = stringneeded;
  373.       if (stringused > p->stringlen) {
  374.     stringused = (is_string ? p->stringlen : 0);
  375.     if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
  376.       }
  377.       if (!stringused)
  378.     SIVAL(p->structbuf,0,0);
  379.       else {
  380.     SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
  381.     memcpy(p->stringbuf,str?str:"",stringused);
  382.     if (is_string) p->stringbuf[stringused-1] = '\0';
  383.     p->stringbuf += stringused;
  384.     p->stringlen -= stringused;
  385.     p->usedlen += stringused;
  386.       }
  387.     }
  388.     p->neededlen += stringneeded;
  389.   }
  390.   p->neededlen += needed;
  391.   if (p->buflen >= needed) {
  392.     p->structbuf += needed;
  393.     p->buflen -= needed;
  394.     p->usedlen += needed;
  395.   }
  396.   else {
  397.     if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
  398.   }
  399.   return 1;
  400. }
  401.  
  402. #if CHECK_TYPES
  403. #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
  404. #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
  405. #else
  406. #define PACK(desc,t,v) package(desc,v)
  407. #define PACKl(desc,t,v,l) package(desc,v,l)
  408. #endif
  409.  
  410. static void PACKI(struct pack_desc* desc,char *t,int v)
  411. {
  412.   PACK(desc,t,v);
  413. }
  414.  
  415. static void PACKS(struct pack_desc* desc,char *t,char *v)
  416. {
  417.   PACK(desc,t,v);
  418. }
  419.  
  420.  
  421. static void PackDriverData(struct pack_desc* desc)
  422. {
  423.   char drivdata[4+4+32];
  424.   SIVAL(drivdata,0,sizeof drivdata); /* cb */
  425.   SIVAL(drivdata,4,1000);    /* lVersion */
  426.   memset(drivdata+8,0,32);    /* szDeviceName */
  427.   strcpy(drivdata+8,"NULL");
  428.   PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
  429. }
  430.  
  431. static int check_printq_info(struct pack_desc* desc,
  432.                   int uLevel, const char* id1, const char* id2)
  433. {
  434.   desc->subformat = NULL;
  435.   switch( uLevel ) {
  436.   case 0:
  437.     desc->format = "B13";
  438.     break;
  439.   case 1:
  440.     desc->format = "B13BWWWzzzzzWW";
  441.     break;
  442.   case 2:
  443.     desc->format = "B13BWWWzzzzzWN";
  444.     desc->subformat = "WB21BB16B10zWWzDDz";
  445.     break;
  446.   case 3:
  447.     desc->format = "zWWWWzzzzWWzzl";
  448.     break;
  449.   case 4:
  450.     desc->format = "zWWWWzzzzWNzzl";
  451.     desc->subformat = "WWzWWDDzz";
  452.     break;
  453.   case 5:
  454.     desc->format = "z";
  455.     break;
  456.   default: return False;
  457.   }
  458.   if (strcmp(desc->format,id1) != 0) return False;
  459.   if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
  460.   return True;
  461. }
  462.  
  463. static void fill_printjob_info(int cnum, int snum, int uLevel,
  464.                    struct pack_desc* desc,
  465.                    print_queue_struct* queue, int n)
  466. {
  467.   time_t t = queue->time;
  468.  
  469.   /* the client expects localtime */
  470.   t += GMT_TO_LOCAL*TimeDiff(t);
  471.  
  472.   PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
  473.   if (uLevel == 1) {
  474.     PACKS(desc,"B21",queue->user); /* szUserName */
  475.     PACKS(desc,"B","");        /* pad */
  476.     PACKS(desc,"B16","");    /* szNotifyName */
  477.     PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
  478.     PACKS(desc,"z","");        /* pszParms */
  479.     PACKI(desc,"W",n+1);        /* uPosition */
  480.     PACKI(desc,"W",queue->status); /* fsStatus */
  481.     PACKS(desc,"z","");        /* pszStatus */
  482.     PACKI(desc,"D",queue->time); /* ulSubmitted */
  483.     PACKI(desc,"D",queue->size); /* ulSize */
  484.     PACKS(desc,"z",queue->file); /* pszComment */
  485.   }
  486.   if (uLevel == 2 || uLevel == 3) {
  487.     PACKI(desc,"W",queue->priority);        /* uPriority */
  488.     PACKS(desc,"z",queue->user); /* pszUserName */
  489.     PACKI(desc,"W",n+1);        /* uPosition */
  490.     PACKI(desc,"W",queue->status); /* fsStatus */
  491.     PACKI(desc,"D",queue->time); /* ulSubmitted */
  492.     PACKI(desc,"D",queue->size); /* ulSize */
  493.     PACKS(desc,"z","Samba");    /* pszComment */
  494.     PACKS(desc,"z",queue->file); /* pszDocument */
  495.     if (uLevel == 3) {
  496.       PACKS(desc,"z","");    /* pszNotifyName */
  497.       PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
  498.       PACKS(desc,"z","");    /* pszParms */
  499.       PACKS(desc,"z","");    /* pszStatus */
  500.       PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
  501.       PACKS(desc,"z","lpd");    /* pszQProcName */
  502.       PACKS(desc,"z","");    /* pszQProcParms */
  503.       PACKS(desc,"z","NULL"); /* pszDriverName */
  504.       PackDriverData(desc);    /* pDriverData */
  505.       PACKS(desc,"z","");    /* pszPrinterName */
  506.     }
  507.   }
  508. }
  509.  
  510. static void fill_printq_info(int cnum, int snum, int uLevel,
  511.                   struct pack_desc* desc,
  512.                   int count, print_queue_struct* queue,
  513.                   print_status_struct* status)
  514. {
  515.   if (uLevel < 3) {
  516.     PACKS(desc,"B13",SERVICE(snum));
  517.   } else {
  518.     PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
  519.   }
  520.   if (uLevel == 1 || uLevel == 2) {
  521.     PACKS(desc,"B","");        /* alignment */
  522.     PACKI(desc,"W",5);        /* priority */
  523.     PACKI(desc,"W",0);        /* start time */
  524.     PACKI(desc,"W",0);        /* until time */
  525.     PACKS(desc,"z","");        /* pSepFile */
  526.     PACKS(desc,"z","lpd");    /* pPrProc */
  527.     PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
  528.     PACKS(desc,"z","");        /* pParms */
  529.     if (snum < 0) {
  530.       PACKS(desc,"z","UNKNOWN PRINTER");
  531.       PACKI(desc,"W",LPSTAT_ERROR);
  532.     }
  533.     else if (!status || !status->message[0]) {
  534.       PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
  535.       PACKI(desc,"W",LPSTAT_OK); /* status */
  536.     } else {
  537.       PACKS(desc,"z",status->message);
  538.       PACKI(desc,"W",status->status); /* status */
  539.     }
  540.     PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
  541.   }
  542.   if (uLevel == 3 || uLevel == 4) {
  543.     PACKI(desc,"W",5);        /* uPriority */
  544.     PACKI(desc,"W",0);        /* uStarttime */
  545.     PACKI(desc,"W",0);        /* uUntiltime */
  546.     PACKI(desc,"W",5);        /* pad1 */
  547.     PACKS(desc,"z","");        /* pszSepFile */
  548.     PACKS(desc,"z","lpd");    /* pszPrProc */
  549.     PACKS(desc,"z","");        /* pszParms */
  550.     if (!status || !status->message[0]) {
  551.       PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
  552.       PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
  553.     } else {
  554.       PACKS(desc,"z",status->message); /* pszComment */
  555.       PACKI(desc,"W",status->status); /* fsStatus */
  556.     }
  557.     PACKI(desc,(uLevel == 3 ? "W" : "N"),count);    /* cJobs */
  558.     PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
  559.     PACKS(desc,"z","NULL");    /* pszDriverName */
  560.     PackDriverData(desc);    /* pDriverData */
  561.   }
  562.   if (uLevel == 2 || uLevel == 4) {
  563.     int i;
  564.     for (i=0;i<count;i++)
  565.       fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
  566.   }
  567.  
  568.   DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
  569. }
  570.  
  571. static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
  572.                  int mdrcnt,int mprcnt,
  573.                  char **rdata,char **rparam,
  574.                  int *rdata_len,int *rparam_len)
  575. {
  576.   char *str1 = param+2;
  577.   char *str2 = skip_string(str1,1);
  578.   char *p = skip_string(str2,1);
  579.   char *QueueName = p;
  580.   int uLevel,cbBuf;
  581.   int count=0;
  582.   int snum;
  583.   char* str3;
  584.   struct pack_desc desc;
  585.   print_queue_struct *queue=NULL;
  586.   print_status_struct status;
  587.   
  588.   bzero(&status,sizeof(status));
  589.   bzero(&desc,sizeof(desc));
  590.  
  591.   p = skip_string(p,1);
  592.   uLevel = SVAL(p,0);
  593.   cbBuf = SVAL(p,2);
  594.   str3 = p + 4;
  595.  
  596.   if ((p = strchr(QueueName,'%'))) *p = 0;
  597.  
  598.   DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
  599.  
  600.   /* check it's a supported varient */
  601.   if (!prefix_ok(str1,"zWrLh")) return False;
  602.   if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
  603.  
  604.   snum = lp_servicenumber(QueueName);
  605.   if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
  606.     int pnum = lp_servicenumber(PRINTERS_NAME);
  607.     if (pnum >= 0) {
  608.       lp_add_printer(QueueName,pnum);
  609.       snum = lp_servicenumber(QueueName);
  610.     }
  611.   }
  612.   
  613.   if (snum < 0 || !VALID_SNUM(snum)) return(False);
  614.  
  615.   count = get_printqueue(snum,cnum,&queue,&status);
  616.   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
  617.   desc.base = *rdata;
  618.   desc.buflen = mdrcnt;
  619.   if (init_package(&desc,1,count)) {
  620.     desc.subcount = count;
  621.     fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
  622.   }
  623.  
  624.   *rdata_len = desc.usedlen;
  625.   
  626.   *rparam_len = 6;
  627.   *rparam = REALLOC(*rparam,*rparam_len);
  628.   SSVALS(*rparam,0,desc.errcode);
  629.   SSVAL(*rparam,2,0);
  630.   SSVAL(*rparam,4,desc.neededlen);
  631.   
  632.   DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
  633.  
  634.   if (queue) free(queue);
  635.   
  636.   return(True);
  637. }
  638.  
  639.  
  640. /****************************************************************************
  641.   view list of all print jobs on all queues
  642.   ****************************************************************************/
  643. static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
  644.                    int mdrcnt, int mprcnt,
  645.                    char **rdata, char** rparam,
  646.                    int *rdata_len, int *rparam_len)
  647. {
  648.   char *param_format = param+2;
  649.   char *output_format1 = skip_string(param_format,1);
  650.   char *p = skip_string(output_format1,1);
  651.   int uLevel = SVAL(p,0);
  652.   char *output_format2 = p + 4;
  653.   int services = lp_numservices();
  654.   int i, n;
  655.   struct pack_desc desc;
  656.   print_queue_struct **queue = NULL;
  657.   print_status_struct *status = NULL;
  658.   int* subcntarr = NULL;
  659.   int queuecnt, subcnt=0, succnt=0;
  660.  
  661.   bzero(&desc,sizeof(desc));
  662.  
  663.   DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
  664.  
  665.   if (prefix_ok(param_format,"WrLeh")) return False;
  666.   if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
  667.     return False;
  668.   queuecnt = 0;
  669.   for (i = 0; i < services; i++)
  670.     if (lp_print_ok(i) && lp_browseable(i))
  671.       queuecnt++;
  672.   if (uLevel > 0) {
  673.     queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
  674.     memset(queue,0,queuecnt*sizeof(print_queue_struct*));
  675.     status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
  676.     memset(status,0,queuecnt*sizeof(print_status_struct));
  677.     subcntarr = (int*)malloc(queuecnt*sizeof(int));
  678.     subcnt = 0;
  679.     n = 0;
  680.     for (i = 0; i < services; i++)
  681.       if (lp_print_ok(i) && lp_browseable(i)) {
  682.      subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
  683.      subcnt += subcntarr[n];
  684.      n++;
  685.       }
  686.   }
  687.   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
  688.   desc.base = *rdata;
  689.   desc.buflen = mdrcnt;
  690.  
  691.   if (init_package(&desc,queuecnt,subcnt)) {
  692.     n = 0;
  693.     succnt = 0;
  694.     for (i = 0; i < services; i++)
  695.       if (lp_print_ok(i) && lp_browseable(i)) {
  696.     fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
  697.     n++;
  698.     if (desc.errcode == NERR_Success) succnt = n;
  699.       }
  700.   }
  701.  
  702.   if (subcntarr) free(subcntarr);
  703.  
  704.   *rdata_len = desc.usedlen;
  705.   *rparam_len = 8;
  706.   *rparam = REALLOC(*rparam,*rparam_len);
  707.   SSVALS(*rparam,0,desc.errcode);
  708.   SSVAL(*rparam,2,0);
  709.   SSVAL(*rparam,4,succnt);
  710.   SSVAL(*rparam,6,queuecnt);
  711.   
  712.   for (i = 0; i < queuecnt; i++) {
  713.     if (queue && queue[i]) free(queue[i]);
  714.   }
  715.  
  716.   if (queue) free(queue);
  717.   if (status) free(status);
  718.   
  719.   return True;
  720. }
  721.  
  722. /****************************************************************************
  723.   get info level for a server list query
  724.   ****************************************************************************/
  725. static BOOL check_server_info(int uLevel, char* id)
  726. {
  727.   switch( uLevel ) {
  728.   case 0:
  729.     if (strcmp(id,"B16") != 0) return False;
  730.     break;
  731.   case 1:
  732.     if (strcmp(id,"B16BBDz") != 0) return False;
  733.     break;
  734.   default: 
  735.     return False;
  736.   }
  737.   return True;
  738. }
  739.  
  740. struct server_info_struct {
  741.   fstring name;
  742.   uint32 type;
  743.   fstring comment;
  744. };
  745.  
  746.  
  747. /*******************************************************************
  748.   get server info lists from the files saved by nmbd. Return the
  749.   number of entries
  750.   ******************************************************************/
  751. static int get_server_info(uint32 servertype,
  752.                struct server_info_struct **servers)
  753. {
  754.   FILE *f;
  755.   pstring fname;
  756.   int count=0;
  757.   int alloced=0;
  758.   pstring line;
  759.  
  760.   strcpy(fname,lp_lockdir());
  761.   trim_string(fname,NULL,"/");
  762.   strcat(fname,"/");
  763.   strcat(fname,SERVER_LIST);
  764.  
  765.   f = fopen(fname,"r");
  766.  
  767.   if (!f) {
  768.     DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
  769.     return(0);
  770.   }
  771.  
  772.   if (servertype == SV_TYPE_ALL)
  773.     servertype &= ~SV_TYPE_DOMAIN_ENUM;
  774.  
  775.   while (!feof(f)) {
  776.     fstring stype;
  777.     struct server_info_struct *s;
  778.     char *ptr = line;
  779.     *ptr = 0;
  780.     fgets(line,sizeof(line)-1,f);
  781.     if (!*line) continue;
  782.  
  783.     if (count == alloced) {
  784.       alloced += 10;
  785.       (*servers) = (struct server_info_struct *)
  786.     Realloc(*servers,sizeof(**servers)*alloced);
  787.       if (!(*servers)) return(0);
  788.       bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
  789.     }
  790.     s = &(*servers)[count];
  791.  
  792.     if (!next_token(&ptr,s->name,NULL)) continue;
  793.     if (!next_token(&ptr,stype,NULL)) continue;
  794.     if (!next_token(&ptr,s->comment,NULL)) continue;
  795.     if (sscanf(stype,"%X",&s->type) != 1) continue;
  796.  
  797.     if (!(servertype & s->type) || 
  798.     ((s->type&SV_TYPE_DOMAIN_ENUM) && 
  799.      !(servertype&SV_TYPE_DOMAIN_ENUM))) continue;
  800.  
  801.     count++;
  802.   }
  803.  
  804.   fclose(f);
  805.   return(count);
  806. }
  807.  
  808. /*******************************************************************
  809.   fill in a server info structure
  810.   ******************************************************************/
  811. static int fill_server_info(struct server_info_struct *service,
  812.                 int uLevel,char **buf, int *buflen,
  813.                 char **stringbuf, int *stringspace, char *baseaddr)
  814. {
  815.   int struct_len;
  816.   char* p;
  817.   char* p2;
  818.   int l2;
  819.   int len;
  820.  
  821.   switch (uLevel) {
  822.   case 0: struct_len = 16; break;
  823.   case 1: struct_len = 26; break;
  824.   default: return -1;
  825.   }  
  826.  
  827.   if (!buf)
  828.     {
  829.       len = 0;
  830.       switch (uLevel) 
  831.     {
  832.     case 1:
  833.       len = strlen(service->comment)+1;
  834.       break;
  835.     }
  836.  
  837.       if (buflen) *buflen = struct_len;
  838.       if (stringspace) *stringspace = len;
  839.       return struct_len + len;
  840.     }
  841.   
  842.   len = struct_len;
  843.   p = *buf;
  844.   if (*buflen < struct_len) return -1;
  845.   if (stringbuf)
  846.     {
  847.       p2 = *stringbuf;
  848.       l2 = *stringspace;
  849.     }
  850.   else
  851.     {
  852.       p2 = p + struct_len;
  853.       l2 = *buflen - struct_len;
  854.     }
  855.   if (!baseaddr) baseaddr = p;
  856.   
  857.   switch (uLevel)
  858.     {
  859.     case 0:
  860.       StrnCpy(p,service->name,15);
  861.       break;
  862.  
  863.     case 1:
  864.       StrnCpy(p,service->name,15);
  865.       SIVAL(p,18,service->type);
  866.       SIVAL(p,22,PTR_DIFF(p2,baseaddr));
  867.       len += CopyAndAdvance(&p2,service->comment,&l2);
  868.       break;
  869.     }
  870.  
  871.   if (stringbuf)
  872.     {
  873.       *buf = p + struct_len;
  874.       *buflen -= struct_len;
  875.       *stringbuf = p2;
  876.       *stringspace = l2;
  877.     }
  878.   else
  879.     {
  880.       *buf = p2;
  881.       *buflen -= len;
  882.     }
  883.   return len;
  884. }
  885.  
  886.  
  887. /****************************************************************************
  888.   view list of servers available (or possibly domains). The info is
  889.   extracted from lists saved by nmbd on the local host
  890.   ****************************************************************************/
  891. static BOOL api_RNetServerEnum(int cnum,int uid, char *param,char *data,
  892.                    int mdrcnt,int mprcnt,
  893.                    char **rdata,char **rparam,
  894.                    int *rdata_len,int *rparam_len)
  895. {
  896.   char *str1 = param+2;
  897.   char *str2 = skip_string(str1,1);
  898.   char *p = skip_string(str2,1);
  899.   int uLevel = SVAL(p,0);
  900.   int buf_len = SVAL(p,2);
  901.   uint32 servertype = IVAL(p,4);
  902.   char *p2;
  903.   int data_len, fixed_len, string_len;
  904.   int f_len, s_len;
  905.   struct server_info_struct *servers=NULL;
  906.   int counted=0,total=0;
  907.   int i;
  908.  
  909.   if (!prefix_ok(str1,"WrLehD")) return False;
  910.   if (!check_server_info(uLevel,str2)) return False;
  911.   
  912.   if (lp_browse_list())
  913.     total = get_server_info(servertype,&servers);
  914.  
  915.   data_len = fixed_len = string_len = 0;
  916.  
  917.   for (i=0;i<total;i++) {
  918.     data_len += fill_server_info(&servers[i],uLevel,0,&f_len,0,&s_len,0);
  919.     if (data_len <= buf_len) {
  920.       counted++;
  921.       fixed_len += f_len;
  922.       string_len += s_len;
  923.     }
  924.   }
  925.  
  926.   *rdata_len = fixed_len + string_len;
  927.   *rdata = REALLOC(*rdata,*rdata_len);
  928.   bzero(*rdata,*rdata_len);
  929.   
  930.   p2 = (*rdata) + fixed_len;    /* auxillery data (strings) will go here */
  931.   p = *rdata;
  932.   f_len = fixed_len;
  933.   s_len = string_len;
  934.   for (i = 0; i < counted;i++)
  935.     fill_server_info(&servers[i],uLevel,&p,&f_len,&p2,&s_len,*rdata);
  936.   
  937.   *rparam_len = 8;
  938.   *rparam = REALLOC(*rparam,*rparam_len);
  939.   SSVAL(*rparam,0,NERR_Success);
  940.   SSVAL(*rparam,2,0);
  941.   SSVAL(*rparam,4,counted);
  942.   SSVAL(*rparam,6,total);
  943.  
  944.   if (servers) free(servers);
  945.  
  946.   DEBUG(4,("NetServerEnum uLevel=%d counted=%d total=%d\n",uLevel,counted,total));
  947.  
  948.   return(True);
  949. }
  950.  
  951.  
  952.  
  953. /****************************************************************************
  954.   get info about a share
  955.   ****************************************************************************/
  956. static BOOL check_share_info(int uLevel, char* id)
  957. {
  958.   switch( uLevel ) {
  959.   case 0:
  960.     if (strcmp(id,"B13") != 0) return False;
  961.     break;
  962.   case 1:
  963.     if (strcmp(id,"B13BWz") != 0) return False;
  964.     break;
  965.   case 2:
  966.     if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
  967.     break;
  968.   case 91:
  969.     if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
  970.     break;
  971.   default: return False;
  972.   }
  973.   return True;
  974. }
  975.  
  976. static int fill_share_info(int cnum, int snum, int uLevel,
  977.                 char** buf, int* buflen,
  978.                 char** stringbuf, int* stringspace, char* baseaddr)
  979. {
  980.   int struct_len;
  981.   char* p;
  982.   char* p2;
  983.   int l2;
  984.   int len;
  985.  
  986.   switch( uLevel ) {
  987.   case 0: struct_len = 13; break;
  988.   case 1: struct_len = 20; break;
  989.   case 2: struct_len = 40; break;
  990.   case 91: struct_len = 68; break;
  991.   default: return -1;
  992.   }
  993.   
  994.  
  995.   if (!buf)
  996.     {
  997.       len = 0;
  998.       if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
  999.       if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
  1000.       if (buflen) *buflen = struct_len;
  1001.       if (stringspace) *stringspace = len;
  1002.       return struct_len + len;
  1003.     }
  1004.   
  1005.   len = struct_len;
  1006.   p = *buf;
  1007.   if ((*buflen) < struct_len) return -1;
  1008.   if (stringbuf)
  1009.     {
  1010.       p2 = *stringbuf;
  1011.       l2 = *stringspace;
  1012.     }
  1013.   else
  1014.     {
  1015.       p2 = p + struct_len;
  1016.       l2 = (*buflen) - struct_len;
  1017.     }
  1018.   if (!baseaddr) baseaddr = p;
  1019.   
  1020.   StrnCpy(p,lp_servicename(snum),13);
  1021.   
  1022.   if (uLevel > 0)
  1023.     {
  1024.       int type;
  1025.       CVAL(p,13) = 0;
  1026.       type = STYPE_DISKTREE;
  1027.       if (lp_print_ok(snum)) type = STYPE_PRINTQ;
  1028.       if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
  1029.       SSVAL(p,14,type);        /* device type */
  1030.       SIVAL(p,16,PTR_DIFF(p2,baseaddr));
  1031.       len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
  1032.     }
  1033.   
  1034.   if (uLevel > 1)
  1035.     {
  1036.       SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
  1037.       SSVALS(p,22,-1);        /* max uses */
  1038.       SSVAL(p,24,1); /* current uses */
  1039.       SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
  1040.       len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
  1041.       memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
  1042.     }
  1043.   
  1044.   if (uLevel > 2)
  1045.     {
  1046.       memset(p+40,0,SHPWLEN+2);
  1047.       SSVAL(p,50,0);
  1048.       SIVAL(p,52,0);
  1049.       SSVAL(p,56,0);
  1050.       SSVAL(p,58,0);
  1051.       SIVAL(p,60,0);
  1052.       SSVAL(p,64,0);
  1053.       SSVAL(p,66,0);
  1054.     }
  1055.        
  1056.   if (stringbuf)
  1057.     {
  1058.       (*buf) = p + struct_len;
  1059.       (*buflen) -= struct_len;
  1060.       (*stringbuf) = p2;
  1061.       (*stringspace) = l2;
  1062.     }
  1063.   else
  1064.     {
  1065.       (*buf) = p2;
  1066.       (*buflen) -= len;
  1067.     }
  1068.   return len;
  1069. }
  1070.  
  1071. static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
  1072.                  int mdrcnt,int mprcnt,
  1073.                  char **rdata,char **rparam,
  1074.                  int *rdata_len,int *rparam_len)
  1075. {
  1076.   char *str1 = param+2;
  1077.   char *str2 = skip_string(str1,1);
  1078.   char *netname = skip_string(str2,1);
  1079.   char *p = skip_string(netname,1);
  1080.   int uLevel = SVAL(p,0);
  1081.   int snum = find_service(netname);
  1082.   
  1083.   if (snum < 0) return False;
  1084.   
  1085.   /* check it's a supported varient */
  1086.   if (!prefix_ok(str1,"zWrLh")) return False;
  1087.   if (!check_share_info(uLevel,str2)) return False;
  1088.  
  1089.   *rdata = REALLOC(*rdata,mdrcnt);
  1090.   p = *rdata;
  1091.   *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
  1092.   if (*rdata_len < 0) return False;
  1093.  
  1094.   *rparam_len = 6;
  1095.   *rparam = REALLOC(*rparam,*rparam_len);
  1096.   SSVAL(*rparam,0,NERR_Success);
  1097.   SSVAL(*rparam,2,0);        /* converter word */
  1098.   SSVAL(*rparam,4,*rdata_len);
  1099.  
  1100.   return(True);
  1101. }
  1102.  
  1103. /****************************************************************************
  1104.   view list of shares available
  1105.   ****************************************************************************/
  1106. static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
  1107.                     int mdrcnt,int mprcnt,
  1108.                     char **rdata,char **rparam,
  1109.                     int *rdata_len,int *rparam_len)
  1110. {
  1111.   char *str1 = param+2;
  1112.   char *str2 = skip_string(str1,1);
  1113.   char *p = skip_string(str2,1);
  1114.   int uLevel = SVAL(p,0);
  1115.   int buf_len = SVAL(p,2);
  1116.   char *p2;
  1117.   int count=lp_numservices();
  1118.   int total=0,counted=0;
  1119.   int i;
  1120.   int data_len, fixed_len, string_len;
  1121.   int f_len, s_len;
  1122.  
  1123.   if (!prefix_ok(str1,"WrLeh")) return False;
  1124.   if (!check_share_info(uLevel,str2)) return False;
  1125.   
  1126.   data_len = fixed_len = string_len = 0;
  1127.   for (i=0;i<count;i++)
  1128.     if (lp_browseable(i))
  1129.       {
  1130.       total++;
  1131.      data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
  1132.      if (data_len <= buf_len)
  1133.        {
  1134.          counted++;
  1135.          fixed_len += f_len;
  1136.          string_len += s_len;
  1137.        }
  1138.       }
  1139.   *rdata_len = fixed_len + string_len;
  1140.   *rdata = REALLOC(*rdata,*rdata_len);
  1141.   memset(*rdata,0,*rdata_len);
  1142.   
  1143.   p2 = (*rdata) + fixed_len;    /* auxillery data (strings) will go here */
  1144.   p = *rdata;
  1145.   f_len = fixed_len;
  1146.   s_len = string_len;
  1147.   for (i = 0; i < count;i++)
  1148.     if (lp_browseable(i))
  1149.       if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
  1150.      break;
  1151.   
  1152.   *rparam_len = 8;
  1153.   *rparam = REALLOC(*rparam,*rparam_len);
  1154.   SSVAL(*rparam,0,NERR_Success);
  1155.   SSVAL(*rparam,2,0);
  1156.   SSVAL(*rparam,4,counted);
  1157.   SSVAL(*rparam,6,total);
  1158.   
  1159.   DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
  1160.         counted,total,uLevel,
  1161.          buf_len,*rdata_len,mdrcnt));
  1162.   return(True);
  1163. }
  1164.  
  1165.  
  1166.  
  1167. /****************************************************************************
  1168.   get the time of day info
  1169.   ****************************************************************************/
  1170. static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
  1171.                  int mdrcnt,int mprcnt,
  1172.                  char **rdata,char **rparam,
  1173.                  int *rdata_len,int *rparam_len)
  1174. {
  1175.   char *p;
  1176.   *rparam_len = 4;
  1177.   *rparam = REALLOC(*rparam,*rparam_len);
  1178.  
  1179.   *rdata_len = 21;
  1180.   *rdata = REALLOC(*rdata,*rdata_len);
  1181.  
  1182.   SSVAL(*rparam,0,NERR_Success);
  1183.   SSVAL(*rparam,2,0);        /* converter word */
  1184.  
  1185.   p = *rdata;
  1186.  
  1187.   {
  1188.     struct tm *t;
  1189.     time_t unixdate = time(NULL);
  1190.  
  1191.     put_dos_date3(p,0,unixdate); /* this is the time that is looked at
  1192.                     by NT in a "net time" operation,
  1193.                     it seems to ignore the one below */
  1194.  
  1195.     /* the client expects to get localtime, not GMT, in this bit 
  1196.        (I think, this needs testing) */
  1197.     t = LocalTime(&unixdate,GMT_TO_LOCAL);
  1198.  
  1199.     SIVAL(p,4,0);        /* msecs ? */
  1200.     CVAL(p,8) = t->tm_hour;
  1201.     CVAL(p,9) = t->tm_min;
  1202.     CVAL(p,10) = t->tm_sec;
  1203.     CVAL(p,11) = 0;        /* hundredths of seconds */
  1204.     SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
  1205.     SSVAL(p,14,10000);        /* timer interval in 0.0001 of sec */
  1206.     CVAL(p,16) = t->tm_mday;
  1207.     CVAL(p,17) = t->tm_mon + 1;
  1208.     SSVAL(p,18,1900+t->tm_year);
  1209.     CVAL(p,20) = t->tm_wday;
  1210.   }
  1211.  
  1212.  
  1213.   return(True);
  1214. }
  1215.  
  1216. /****************************************************************************
  1217.   set the user password
  1218.   ****************************************************************************/
  1219. static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
  1220.                 int mdrcnt,int mprcnt,
  1221.                 char **rdata,char **rparam,
  1222.                 int *rdata_len,int *rparam_len)
  1223. {
  1224.   char *p = skip_string(param+2,2);
  1225.   fstring user;
  1226.   fstring pass1,pass2;
  1227.  
  1228.   strcpy(user,p);
  1229.  
  1230.   p = skip_string(p,1);
  1231.  
  1232.   StrnCpy(pass1,p,16);
  1233.   StrnCpy(pass2,p+16,16);
  1234.  
  1235.   *rparam_len = 4;
  1236.   *rparam = REALLOC(*rparam,*rparam_len);
  1237.  
  1238.   *rdata_len = 0;
  1239.  
  1240.   SSVAL(*rparam,0,NERR_Success);
  1241.   SSVAL(*rparam,2,0);        /* converter word */
  1242.  
  1243.   DEBUG(3,("Set password for <%s>\n",user));
  1244.  
  1245.   if (!password_ok(user,pass1,strlen(pass1),NULL,False) || 
  1246.       !chgpasswd(user,pass1,pass2))
  1247.     SSVAL(*rparam,0,NERR_badpass);
  1248.  
  1249.   bzero(pass1,sizeof(fstring));
  1250.   bzero(pass2,sizeof(fstring));     
  1251.      
  1252.   return(True);
  1253. }
  1254.  
  1255. /****************************************************************************
  1256.   delete a print job
  1257.   Form: <W> <> 
  1258.   ****************************************************************************/
  1259. static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
  1260.                 int mdrcnt,int mprcnt,
  1261.                 char **rdata,char **rparam,
  1262.                 int *rdata_len,int *rparam_len)
  1263. {
  1264.   int function = SVAL(param,0);
  1265.   char *str1 = param+2;
  1266.   char *str2 = skip_string(str1,1);
  1267.   char *p = skip_string(str2,1);
  1268.   int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
  1269.                    by the print queue api */
  1270.   int snum = (SVAL(p,0)>>8);  
  1271.   int i, count;
  1272.  
  1273.  
  1274.   /* check it's a supported varient */
  1275.   if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
  1276.     return(False);
  1277.  
  1278.   *rparam_len = 4;
  1279.   *rparam = REALLOC(*rparam,*rparam_len);
  1280.  
  1281.   *rdata_len = 0;
  1282.  
  1283.   SSVAL(*rparam,0,NERR_Success);
  1284.  
  1285.   if (snum >= 0 && VALID_SNUM(snum))
  1286.     {
  1287.       print_queue_struct *queue=NULL;
  1288.       lpq_reset(snum);
  1289.       count = get_printqueue(snum,cnum,&queue,NULL);
  1290.   
  1291.       for (i=0;i<count;i++)
  1292.       if ((queue[i].job%0xFF) == jobid)
  1293.         {
  1294.          switch (function) {
  1295.         case 81:        /* delete */ 
  1296.           DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
  1297.           del_printqueue(cnum,snum,queue[i].job);
  1298.           break;
  1299.         case 82:        /* pause */
  1300.         case 83:        /* resume */
  1301.           DEBUG(3,("%s queue entry %d\n",
  1302.                (function==82?"pausing":"resuming"),queue[i].job));
  1303.           status_printjob(cnum,snum,queue[i].job,
  1304.                   (function==82?LPQ_PAUSED:LPQ_QUEUED));
  1305.           break;
  1306.          }
  1307.          break;
  1308.         }
  1309.   
  1310.       if (i==count)
  1311.     SSVAL(*rparam,0,NERR_JobNotFound);
  1312.  
  1313.       if (queue) free(queue);
  1314.     }
  1315.  
  1316.   SSVAL(*rparam,2,0);        /* converter word */
  1317.  
  1318.   return(True);
  1319. }
  1320.  
  1321. static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data,
  1322.                  int mdrcnt,int mprcnt,
  1323.                  char **rdata,char **rparam,
  1324.                  int *rdata_len,int *rparam_len)
  1325. {
  1326.   char *str1 = param+2;
  1327.   char *str2 = skip_string(str1,1);
  1328.   char *QueueName = skip_string(str2,1);
  1329.   int snum;
  1330.  
  1331.   /* check it's a supported varient */
  1332.   if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
  1333.     return(False);
  1334.  
  1335.   *rparam_len = 4;
  1336.   *rparam = REALLOC(*rparam,*rparam_len);
  1337.  
  1338.   *rdata_len = 0;
  1339.  
  1340.   SSVAL(*rparam,0,NERR_Success);
  1341.   SSVAL(*rparam,2,0);        /* converter word */
  1342.  
  1343.   snum = lp_servicenumber(QueueName);
  1344.   if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
  1345.     int pnum = lp_servicenumber(PRINTERS_NAME);
  1346.     if (pnum >= 0) {
  1347.       lp_add_printer(QueueName,pnum);
  1348.       snum = lp_servicenumber(QueueName);
  1349.     }
  1350.   }
  1351.  
  1352.   if (snum >= 0 && VALID_SNUM(snum)) {
  1353.     print_queue_struct *queue=NULL;
  1354.     int i, count;
  1355.     lpq_reset(snum);
  1356.     
  1357.     count = get_printqueue(snum,cnum,&queue,NULL);
  1358.     for (i = 0; i < count; i++)
  1359.       del_printqueue(cnum,snum,queue[i].job);
  1360.     
  1361.     if (queue) free(queue);
  1362.   }
  1363.  
  1364.   DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
  1365.  
  1366.   return(True);
  1367. }
  1368.  
  1369.  
  1370. /****************************************************************************
  1371.   set the property of a print job (undocumented?)
  1372.   ? function = 0xb -> set name of print job
  1373.   ? function = 0x6 -> move print job up/down
  1374.   Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz> 
  1375.   or   <WWsTP> <WB21BB16B10zWWzDDz> 
  1376. ****************************************************************************/
  1377. static int check_printjob_info(struct pack_desc* desc,
  1378.                    int uLevel, char* id)
  1379. {
  1380.   desc->subformat = NULL;
  1381.   switch( uLevel ) {
  1382.   case 0: desc->format = "W"; break;
  1383.   case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
  1384.   case 2: desc->format = "WWzWWDDzz"; break;
  1385.   case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
  1386.   default: return False;
  1387.   }
  1388.   if (strcmp(desc->format,id) != 0) return False;
  1389.   return True;
  1390. }
  1391.  
  1392. static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
  1393.                    int mdrcnt,int mprcnt,
  1394.                    char **rdata,char **rparam,
  1395.                    int *rdata_len,int *rparam_len)
  1396. {
  1397.   struct pack_desc desc;
  1398.   char *str1 = param+2;
  1399.   char *str2 = skip_string(str1,1);
  1400.   char *p = skip_string(str2,1);
  1401.   int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
  1402.                     by the print queue api */
  1403.   int snum = (SVAL(p,0)>>8);
  1404.   int uLevel = SVAL(p,2);
  1405.   int function = SVAL(p,4);    /* what is this ?? */
  1406.   int i;
  1407.   char *s = data;
  1408.    
  1409.   *rparam_len = 4;
  1410.   *rparam = REALLOC(*rparam,*rparam_len);
  1411.   
  1412.   *rdata_len = 0;
  1413.   
  1414.   /* check it's a supported varient */
  1415.   if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
  1416.     return(False);
  1417.    
  1418.   switch (function) {
  1419.   case 0x6:    /* change job place in the queue, data gives the new place */
  1420.     if (snum >= 0 && VALID_SNUM(snum))
  1421.       {
  1422.     print_queue_struct *queue=NULL;
  1423.     int count;
  1424.   
  1425.     lpq_reset(snum);
  1426.     count = get_printqueue(snum,cnum,&queue,NULL);
  1427.     for (i=0;i<count;i++)    /* find job */
  1428.       if ((queue[i].job%0xFF) == jobid) break;
  1429.          
  1430.     if (i==count) {
  1431.       desc.errcode=NERR_JobNotFound;
  1432.       if (queue) free(queue);
  1433.     }
  1434.     else {
  1435.       desc.errcode=NERR_Success;
  1436.       i++;
  1437. #if 0    
  1438.       {
  1439.         int place= SVAL(data,0);
  1440.         /* we currently have no way of doing this. Can any unix do it? */
  1441.         if (i < place)    /* move down */;
  1442.         else if (i > place )    /* move up */;
  1443.       }
  1444. #endif
  1445.       desc.errcode=NERR_notsupported; /* not yet supported */
  1446.       if (queue) free(queue);
  1447.     }
  1448.       }
  1449.     else desc.errcode=NERR_JobNotFound;
  1450.     break;
  1451.   case 0xb:   /* change print job name, data gives the name */
  1452.     /* jobid, snum should be zero */
  1453.     if (isalpha(*s))
  1454.       {
  1455.     pstring name;
  1456.     int l = 0;
  1457.     while (l<64 && *s)
  1458.       {
  1459.         if (isalnum(*s) || strchr("-._",*s))
  1460.           name[l++] = *s;
  1461.         s++;
  1462.       }      
  1463.     name[l] = 0;
  1464.     
  1465.     DEBUG(3,("Setting print name to %s\n",name));
  1466.     
  1467.     for (i=0;i<MAX_OPEN_FILES;i++)
  1468.       if (Files[i].open && Files[i].print_file)
  1469.         {
  1470.           pstring wd;
  1471.           GetWd(wd);
  1472.           unbecome_user();
  1473.           
  1474.           if (!become_user(Files[i].cnum,uid) || 
  1475.           !become_service(Files[i].cnum,True))
  1476.         break;
  1477.           
  1478.           if (sys_rename(Files[i].name,name) == 0)
  1479.         string_set(&Files[i].name,name);
  1480.           break;
  1481.         }
  1482.       }
  1483.     desc.errcode=NERR_Success;
  1484.   
  1485.     break;
  1486.   default:            /* not implemented */
  1487.     return False;
  1488.   }
  1489.  
  1490.   SSVALS(*rparam,0,desc.errcode);
  1491.   SSVAL(*rparam,2,0);        /* converter word */
  1492.   
  1493.   return(True);
  1494. }
  1495.  
  1496.  
  1497. /****************************************************************************
  1498.   get info about the server
  1499.   ****************************************************************************/
  1500. static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
  1501.                   int mdrcnt,int mprcnt,
  1502.                   char **rdata,char **rparam,
  1503.                   int *rdata_len,int *rparam_len)
  1504. {
  1505.   char *str1 = param+2;
  1506.   char *str2 = skip_string(str1,1);
  1507.   char *p = skip_string(str2,1);
  1508.   int uLevel = SVAL(p,0);
  1509.   char *p2;
  1510.   int struct_len;
  1511.  
  1512.   DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
  1513.  
  1514.   /* check it's a supported varient */
  1515.   if (!prefix_ok(str1,"WrLh")) return False;
  1516.   switch( uLevel ) {
  1517.   case 0:
  1518.     if (strcmp(str2,"B16") != 0) return False;
  1519.     struct_len = 16;
  1520.     break;
  1521.   case 1:
  1522.     if (strcmp(str2,"B16BBDz") != 0) return False;
  1523.     struct_len = 26;
  1524.     break;
  1525.   case 2:
  1526.     if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
  1527.     != 0) return False;
  1528.     struct_len = 134;
  1529.     break;
  1530.   case 3:
  1531.     if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
  1532.     != 0) return False;
  1533.     struct_len = 144;
  1534.     break;
  1535.   case 20:
  1536.     if (strcmp(str2,"DN") != 0) return False;
  1537.     struct_len = 6;
  1538.     break;
  1539.   case 50:
  1540.     if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
  1541.     struct_len = 42;
  1542.     break;
  1543.   default: return False;
  1544.   }
  1545.  
  1546.   *rdata_len = mdrcnt;
  1547.   *rdata = REALLOC(*rdata,*rdata_len);
  1548.  
  1549.   p = *rdata;
  1550.   p2 = p + struct_len;
  1551.   if (uLevel != 20) {
  1552.     StrnCpy(p,local_machine,16);
  1553.     strupper(p);
  1554.   }
  1555.   p += 16;
  1556.   if (uLevel > 0)
  1557.     {
  1558.       struct server_info_struct *servers=NULL;
  1559.       int i,count;
  1560.       pstring comment;
  1561.       uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION|
  1562.     SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE;
  1563.  
  1564.       strcpy(comment,lp_serverstring());
  1565.  
  1566.       if ((count=get_server_info(SV_TYPE_ALL,&servers))>0) {
  1567.     for (i=0;i<count;i++)
  1568.       if (strequal(servers[i].name,local_machine)) {
  1569.         servertype = servers[i].type;
  1570.         strcpy(comment,servers[i].comment);        
  1571.       }
  1572.       }
  1573.       if (servers) free(servers);
  1574.  
  1575.       SCVAL(p,0,2);        /* version_major */
  1576.       SCVAL(p,1,0);        /* version_minor */
  1577.       SIVAL(p,2,servertype);
  1578.       if (mdrcnt == struct_len) {
  1579.     SIVAL(p,6,0);
  1580.       } else {
  1581.     SIVAL(p,6,PTR_DIFF(p2,*rdata));
  1582.     standard_sub(cnum,comment);
  1583.     StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
  1584.     p2 = skip_string(p2,1);
  1585.       }
  1586.     }
  1587.   if (uLevel > 1)
  1588.     {
  1589.       return False;        /* not yet implemented */
  1590.     }
  1591.  
  1592.   *rdata_len = PTR_DIFF(p2,*rdata);
  1593.  
  1594.   *rparam_len = 6;
  1595.   *rparam = REALLOC(*rparam,*rparam_len);
  1596.   SSVAL(*rparam,0,NERR_Success);
  1597.   SSVAL(*rparam,2,0);        /* converter word */
  1598.   SSVAL(*rparam,4,*rdata_len);
  1599.  
  1600.   return(True);
  1601. }
  1602.  
  1603.  
  1604. /****************************************************************************
  1605.   get info about the server
  1606.   ****************************************************************************/
  1607. static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
  1608.                 int mdrcnt,int mprcnt,
  1609.                 char **rdata,char **rparam,
  1610.                 int *rdata_len,int *rparam_len)
  1611. {
  1612.   char *str1 = param+2;
  1613.   char *str2 = skip_string(str1,1);
  1614.   char *p = skip_string(str2,1);
  1615.   char *p2;
  1616.   extern pstring sesssetup_user;
  1617.   int level = SVAL(p,0);
  1618.  
  1619.   DEBUG(4,("NetWkstaGetInfo level %d\n",level));
  1620.  
  1621.   *rparam_len = 6;
  1622.   *rparam = REALLOC(*rparam,*rparam_len);
  1623.  
  1624.   /* check it's a supported varient */
  1625.   if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
  1626.     return(False);
  1627.  
  1628.   *rdata_len = mdrcnt + 1024;
  1629.   *rdata = REALLOC(*rdata,*rdata_len);
  1630.  
  1631.   SSVAL(*rparam,0,NERR_Success);
  1632.   SSVAL(*rparam,2,0);        /* converter word */
  1633.  
  1634.   p = *rdata;
  1635.   p2 = p + 22;
  1636.  
  1637.   SIVAL(p,0,PTR_DIFF(p2,*rdata));
  1638.   strcpy(p2,local_machine);
  1639.   p2 = skip_string(p2,1);
  1640.   p += 4;
  1641.  
  1642.   SIVAL(p,0,PTR_DIFF(p2,*rdata));
  1643.   strcpy(p2,sesssetup_user);
  1644.   p2 = skip_string(p2,1);
  1645.   p += 4;
  1646.  
  1647.   SIVAL(p,0,PTR_DIFF(p2,*rdata));
  1648.   strcpy(p2,my_workgroup());
  1649.   p2 = skip_string(p2,1);
  1650.   p += 4;
  1651.  
  1652.   SCVAL(p,0,2); /* major version?? */
  1653.   SCVAL(p,1,1); /* minor version?? */
  1654.   p += 2;
  1655.  
  1656.   SIVAL(p,0,PTR_DIFF(p2,*rdata));
  1657.   strcpy(p2,my_workgroup());    /* login domain?? */
  1658.   p2 = skip_string(p2,1);
  1659.   p += 4;
  1660.  
  1661.   SIVAL(p,0,PTR_DIFF(p2,*rdata));
  1662.   strcpy(p2,"");
  1663.   p2 = skip_string(p2,1);
  1664.   p += 4;
  1665.  
  1666.   *rdata_len = PTR_DIFF(p2,*rdata);
  1667.  
  1668.   SSVAL(*rparam,4,*rdata_len);
  1669.  
  1670.   return(True);
  1671. }
  1672.  
  1673.  
  1674. /****************************************************************************
  1675.   get info about a user
  1676.   ****************************************************************************/
  1677.  
  1678. #define USER_PRIV_GUEST 0
  1679. #define USER_PRIV_USER 1
  1680. #define USER_PRIV_ADMIN 2
  1681.  
  1682. static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
  1683.                 int mdrcnt,int mprcnt,
  1684.                 char **rdata,char **rparam,
  1685.                 int *rdata_len,int *rparam_len)
  1686. {
  1687.   char *str1 = param+2;
  1688.   char *str2 = skip_string(str1,1);
  1689.   char *UserName = skip_string(str2,1);
  1690.   char *p = skip_string(UserName,1);
  1691.   int uLevel = SVAL(p,0);
  1692.   char *p2;
  1693.  
  1694.   *rparam_len = 6;
  1695.   *rparam = REALLOC(*rparam,*rparam_len);
  1696.  
  1697.   /* check it's a supported varient */
  1698.   if (strcmp(str1,"zWrLh") != 0) return False;
  1699.   switch( uLevel ) {
  1700.   case 0: p2 = "B21"; break;
  1701.   case 1: p2 = "B21BB16DWzzWz"; break;
  1702.   case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
  1703.   case 10: p2 = "B21Bzzz"; break;
  1704.   case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
  1705.   default: return False;
  1706.   }
  1707.   if (strcmp(p2,str2) != 0) return False;
  1708.  
  1709.   *rdata_len = mdrcnt + 1024;
  1710.   *rdata = REALLOC(*rdata,*rdata_len);
  1711.  
  1712.   SSVAL(*rparam,0,NERR_Success);
  1713.   SSVAL(*rparam,2,0);        /* converter word */
  1714.  
  1715.   p = *rdata;
  1716.   p2 = p + 86;
  1717.  
  1718.   memset(p,0,21);
  1719.   strcpy(p,UserName);
  1720.   if (uLevel > 0) {
  1721.     SCVAL(p,21,0);
  1722.     *p2 = 0;
  1723.     if (uLevel >= 10) {
  1724.       SIVAL(p,22,PTR_DIFF(p2,*rdata)); /* comment */
  1725.       SIVAL(p,26,PTR_DIFF(p2,*rdata)); /* user_comment */
  1726.       SIVAL(p,30,PTR_DIFF(p2,*rdata)); /* full name */
  1727.       p2++;
  1728.     }
  1729.     if (uLevel == 11) {
  1730.       SSVAL(p,34,USER_PRIV_ADMIN); /* user privilege */
  1731.       SIVAL(p,36,0);        /* auth flags */
  1732.       SIVAL(p,40,0);        /* password age */
  1733.       SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
  1734.       strcpy(p2,"Y:\\GIGA\\C$\\PRJ\\USERS\\AD");
  1735.       p2 = skip_string(p2,1);
  1736.       SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* parms */
  1737.       strcpy(p2,"");
  1738.       p2 = skip_string(p2,1);
  1739.       SIVAL(p,52,0);        /* last logon */
  1740.       SIVAL(p,56,0);        /* last logoff */
  1741.       SSVALS(p,60,-1);        /* bad pw counts */
  1742.       SSVALS(p,62,-1);        /* num logons */
  1743.       SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* logon server */
  1744.       strcpy(p2,"\\\\GIGA");
  1745.       p2 = skip_string(p2,1);
  1746.       SSVAL(p,68,49);        /* country code */
  1747.       SIVAL(p,70,0);        /* workstations */
  1748.  
  1749.       SIVALS(p,74,-1);        /* max storage */
  1750.       SSVAL(p,78,168);        /* units per week */
  1751.       SIVAL(p,80,PTR_DIFF(p2,*rdata)); /* logon hours */
  1752.       memset(p2,-1,21);
  1753.       p2 += 21;
  1754.       SSVAL(p,84,860);        /* code page */
  1755.     }
  1756.     if (uLevel == 1 || uLevel == 2) {
  1757.       memset(p+22,' ',16);    /* password */
  1758.       SIVALS(p,38,-1);        /* password age */
  1759.       SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */
  1760.       SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
  1761.       strcpy(p2,"\\\\__SAMBA__\\HOMES");
  1762.       p2 = skip_string(p2,1);
  1763.       SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
  1764.       *p2++ = 0;
  1765.       SSVAL(p,52,0);        /* flags */
  1766.       SIVAL(p,54,0);        /* script_path */
  1767.       if (uLevel == 2) {
  1768.     SIVAL(p,60,0);        /* auth_flags */
  1769.     SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
  1770.     strcpy(p2,"<Full Name>");
  1771.     p2 = skip_string(p2,1);
  1772.     SIVAL(p,68,0);        /* urs_comment */
  1773.     SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
  1774.     strcpy(p2,"");
  1775.     p2 = skip_string(p2,1);
  1776.     SIVAL(p,76,0);        /* workstations */
  1777.     SIVAL(p,80,0);        /* last_logon */
  1778.     SIVAL(p,84,0);        /* last_logoff */
  1779.     SIVALS(p,88,-1);        /* acct_expires */
  1780.     SIVALS(p,92,-1);        /* max_storage */
  1781.     SSVAL(p,96,168);    /* units_per_week */
  1782.     SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
  1783.     memset(p2,-1,21);
  1784.     p2 += 21;
  1785.     SSVALS(p,102,-1);    /* bad_pw_count */
  1786.     SSVALS(p,104,-1);    /* num_logons */
  1787.     SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
  1788.     strcpy(p2,"\\\\__SAMBA__");
  1789.     p2 = skip_string(p2,1);
  1790.     SSVAL(p,110,49);    /* country_code */
  1791.     SSVAL(p,112,860);    /* code page */
  1792.       }
  1793.     }
  1794.   }
  1795.  
  1796.   *rdata_len = PTR_DIFF(p2,*rdata);
  1797.  
  1798.   SSVAL(*rparam,4,*rdata_len);    /* is this right?? */
  1799.  
  1800.   return(True);
  1801. }
  1802.  
  1803.  
  1804. /*******************************************************************
  1805.   get groups that a user is a member of
  1806.   ******************************************************************/
  1807. static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
  1808.                  int mdrcnt,int mprcnt,
  1809.                  char **rdata,char **rparam,
  1810.                  int *rdata_len,int *rparam_len)
  1811. {
  1812.   char *str1 = param+2;
  1813.   char *str2 = skip_string(str1,1);
  1814.   char *UserName = skip_string(str2,1);
  1815.   char *p = skip_string(UserName,1);
  1816.   int uLevel = SVAL(p,0);
  1817.   char *p2;
  1818.   int count=0;
  1819.  
  1820.   *rparam_len = 8;
  1821.   *rparam = REALLOC(*rparam,*rparam_len);
  1822.  
  1823.   /* check it's a supported varient */
  1824.   if (strcmp(str1,"zWrLeh") != 0) return False;
  1825.   switch( uLevel ) {
  1826.   case 0: p2 = "B21"; break;
  1827.   default: return False;
  1828.   }
  1829.   if (strcmp(p2,str2) != 0) return False;
  1830.  
  1831.   *rdata_len = mdrcnt + 1024;
  1832.   *rdata = REALLOC(*rdata,*rdata_len);
  1833.  
  1834.   SSVAL(*rparam,0,NERR_Success);
  1835.   SSVAL(*rparam,2,0);        /* converter word */
  1836.  
  1837.   p = *rdata;
  1838.  
  1839.   /* XXXX we need a real SAM database some day */
  1840.   strcpy(p,"Users"); p += 21; count++;
  1841.   strcpy(p,"Domain Users"); p += 21; count++;
  1842.   strcpy(p,"Guests"); p += 21; count++;
  1843.   strcpy(p,"Domain Guests"); p += 21; count++;
  1844.  
  1845.   *rdata_len = PTR_DIFF(p,*rdata);
  1846.  
  1847.   SSVAL(*rparam,4,count);    /* is this right?? */
  1848.   SSVAL(*rparam,6,count);    /* is this right?? */
  1849.  
  1850.   return(True);
  1851. }
  1852.  
  1853.  
  1854. static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
  1855.                 int mdrcnt,int mprcnt,
  1856.                 char **rdata,char **rparam,
  1857.                 int *rdata_len,int *rparam_len)
  1858. {
  1859.   char *str1 = param+2;
  1860.   char *str2 = skip_string(str1,1);
  1861.   char *p = skip_string(str2,1);
  1862.   int uLevel;
  1863.   struct pack_desc desc;
  1864.   char* name;
  1865.  
  1866.   uLevel = SVAL(p,0);
  1867.   name = p + 2;
  1868.  
  1869.   bzero(&desc,sizeof(desc));
  1870.  
  1871.   DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
  1872.  
  1873.   /* check it's a supported varient */
  1874.   if (strcmp(str1,"OOWb54WrLh") != 0) return False;
  1875.   if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
  1876.   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
  1877.   desc.base = *rdata;
  1878.   desc.buflen = mdrcnt;
  1879.   desc.subformat = NULL;
  1880.   desc.format = str2;
  1881.  
  1882.   if (init_package(&desc,1,0)) {
  1883.     PACKI(&desc,"W",0);        /* code */
  1884.     PACKS(&desc,"B21",name);    /* eff. name */
  1885.     PACKS(&desc,"B","");        /* pad */
  1886.     PACKI(&desc,"W",2);        /* priv */
  1887.     PACKI(&desc,"D",0);        /* auth flags XXX */
  1888.     PACKI(&desc,"W",0);        /* num logons */
  1889.     PACKI(&desc,"W",0);        /* bad pw count */
  1890.     PACKI(&desc,"D",-1);        /* last logon */
  1891.     PACKI(&desc,"D",-1);        /* last logoff */
  1892.     PACKI(&desc,"D",-1);        /* logoff time */
  1893.     PACKI(&desc,"D",-1);        /* kickoff time */
  1894.     PACKI(&desc,"D",0);        /* password age */
  1895.     PACKI(&desc,"D",0);        /* password can change */
  1896.     PACKI(&desc,"D",-1);        /* password must change */
  1897.     {
  1898.       fstring mypath;
  1899.       strcpy(mypath,"\\\\");
  1900.       strcat(mypath,local_machine);
  1901.       strupper(mypath);
  1902.       PACKS(&desc,"z",mypath); /* computer */
  1903.     }
  1904.     PACKS(&desc,"z",my_workgroup());/* domain */
  1905.     PACKS(&desc,"z",lp_logon_script());        /* script path */
  1906.     PACKI(&desc,"D",0);        /* reserved */
  1907.   }
  1908.  
  1909.   *rdata_len = desc.usedlen;
  1910.   *rparam_len = 6;
  1911.   *rparam = REALLOC(*rparam,*rparam_len);
  1912.   SSVALS(*rparam,0,desc.errcode);
  1913.   SSVAL(*rparam,2,0);
  1914.   SSVAL(*rparam,4,desc.neededlen);
  1915.  
  1916.   DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
  1917.   return(True);
  1918. }
  1919.  
  1920.  
  1921. /****************************************************************************
  1922.   api_WAccessGetUserPerms
  1923.   ****************************************************************************/
  1924. static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
  1925.                     int mdrcnt,int mprcnt,
  1926.                     char **rdata,char **rparam,
  1927.                     int *rdata_len,int *rparam_len)
  1928. {
  1929.   char *str1 = param+2;
  1930.   char *str2 = skip_string(str1,1);
  1931.   char *user = skip_string(str2,1);
  1932.   char *resource = skip_string(user,1);
  1933.  
  1934.   DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
  1935.  
  1936.   /* check it's a supported varient */
  1937.   if (strcmp(str1,"zzh") != 0) return False;
  1938.   if (strcmp(str2,"") != 0) return False;
  1939.  
  1940.   *rparam_len = 6;
  1941.   *rparam = REALLOC(*rparam,*rparam_len);
  1942.   SSVALS(*rparam,0,0);        /* errorcode */
  1943.   SSVAL(*rparam,2,0);        /* converter word */
  1944.   SSVAL(*rparam,4,0x7f);    /* permission flags */
  1945.  
  1946.   return(True);
  1947. }
  1948.  
  1949. /****************************************************************************
  1950.   api_WPrintJobEnumerate
  1951.   ****************************************************************************/
  1952. static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
  1953.                  int mdrcnt,int mprcnt,
  1954.                  char **rdata,char **rparam,
  1955.                  int *rdata_len,int *rparam_len)
  1956. {
  1957.   char *str1 = param+2;
  1958.   char *str2 = skip_string(str1,1);
  1959.   char *p = skip_string(str2,1);
  1960.   int uJobId = SVAL(p,0);
  1961.   int uLevel,cbBuf;
  1962.   int count;
  1963.   int i;
  1964.   int snum;
  1965.   int job;
  1966.   struct pack_desc desc;
  1967.   print_queue_struct *queue=NULL;
  1968.   print_status_struct status;
  1969.  
  1970.   uLevel = SVAL(p,2);
  1971.   cbBuf = SVAL(p,4);
  1972.  
  1973.   bzero(&desc,sizeof(desc));
  1974.   bzero(&status,sizeof(status));
  1975.  
  1976.   DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
  1977.  
  1978.   /* check it's a supported varient */
  1979.   if (strcmp(str1,"WWrLh") != 0) return False;
  1980.   if (!check_printjob_info(&desc,uLevel,str2)) return False;
  1981.  
  1982.   snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
  1983.   job = uJobId & 0xFF;
  1984.  
  1985.   if (snum < 0 || !VALID_SNUM(snum)) return(False);
  1986.  
  1987.   count = get_printqueue(snum,cnum,&queue,&status);
  1988.   for (i = 0; i < count; i++) {
  1989.     if ((queue[i].job % 0xFF) == job) break;
  1990.   }
  1991.   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
  1992.   desc.base = *rdata;
  1993.   desc.buflen = mdrcnt;
  1994.  
  1995.   if (init_package(&desc,1,0)) {
  1996.     if (i < count) {
  1997.       fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
  1998.       *rdata_len = desc.usedlen;
  1999.     }
  2000.     else {
  2001.       desc.errcode = NERR_JobNotFound;
  2002.       *rdata_len = 0;
  2003.     }
  2004.   }
  2005.  
  2006.   *rparam_len = 6;
  2007.   *rparam = REALLOC(*rparam,*rparam_len);
  2008.   SSVALS(*rparam,0,desc.errcode);
  2009.   SSVAL(*rparam,2,0);
  2010.   SSVAL(*rparam,4,desc.neededlen);
  2011.  
  2012.   if (queue) free(queue);
  2013.  
  2014.   DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
  2015.   return(True);
  2016. }
  2017.  
  2018. static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data,
  2019.                    int mdrcnt,int mprcnt,
  2020.                    char **rdata,char **rparam,
  2021.                    int *rdata_len,int *rparam_len)
  2022. {
  2023.   char *str1 = param+2;
  2024.   char *str2 = skip_string(str1,1);
  2025.   char *p = skip_string(str2,1);
  2026.   char* name = p;
  2027.   int uLevel,cbBuf;
  2028.   int count;
  2029.   int i, succnt=0;
  2030.   int snum;
  2031.   struct pack_desc desc;
  2032.   print_queue_struct *queue=NULL;
  2033.   print_status_struct status;
  2034.  
  2035.   bzero(&desc,sizeof(desc));
  2036.   bzero(&status,sizeof(status));
  2037.  
  2038.   p = skip_string(p,1);
  2039.   uLevel = SVAL(p,0);
  2040.   cbBuf = SVAL(p,2);
  2041.  
  2042.   DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
  2043.  
  2044.   /* check it's a supported varient */
  2045.   if (strcmp(str1,"zWrLeh") != 0) return False;
  2046.   if (uLevel > 2) return False;    /* defined only for uLevel 0,1,2 */
  2047.   if (!check_printjob_info(&desc,uLevel,str2)) return False;
  2048.  
  2049.   snum = lp_servicenumber(name);
  2050.   if (snum < 0 && pcap_printername_ok(name,NULL)) {
  2051.     int pnum = lp_servicenumber(PRINTERS_NAME);
  2052.     if (pnum >= 0) {
  2053.       lp_add_printer(name,pnum);
  2054.       snum = lp_servicenumber(name);
  2055.     }
  2056.   }
  2057.  
  2058.   if (snum < 0 || !VALID_SNUM(snum)) return(False);
  2059.  
  2060.   count = get_printqueue(snum,cnum,&queue,&status);
  2061.   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
  2062.   desc.base = *rdata;
  2063.   desc.buflen = mdrcnt;
  2064.  
  2065.   if (init_package(&desc,count,0)) {
  2066.     succnt = 0;
  2067.     for (i = 0; i < count; i++) {
  2068.       fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
  2069.       if (desc.errcode == NERR_Success) succnt = i+1;
  2070.     }
  2071.   }
  2072.  
  2073.   *rdata_len = desc.usedlen;
  2074.  
  2075.   *rparam_len = 8;
  2076.   *rparam = REALLOC(*rparam,*rparam_len);
  2077.   SSVALS(*rparam,0,desc.errcode);
  2078.   SSVAL(*rparam,2,0);
  2079.   SSVAL(*rparam,4,succnt);
  2080.   SSVAL(*rparam,6,count);
  2081.  
  2082.   if (queue) free(queue);
  2083.  
  2084.   DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
  2085.   return(True);
  2086. }
  2087.  
  2088. static int check_printdest_info(struct pack_desc* desc,
  2089.                 int uLevel, char* id)
  2090. {
  2091.   desc->subformat = NULL;
  2092.   switch( uLevel ) {
  2093.   case 0: desc->format = "B9"; break;
  2094.   case 1: desc->format = "B9B21WWzW"; break;
  2095.   case 2: desc->format = "z"; break;
  2096.   case 3: desc->format = "zzzWWzzzWW"; break;
  2097.   default: return False;
  2098.   }
  2099.   if (strcmp(desc->format,id) != 0) return False;
  2100.   return True;
  2101. }
  2102.  
  2103. static void fill_printdest_info(int cnum, int snum, int uLevel,
  2104.                 struct pack_desc* desc)
  2105. {
  2106.   char buf[100];
  2107.   strcpy(buf,SERVICE(snum));
  2108.   strupper(buf);
  2109.   if (uLevel <= 1) {
  2110.     PACKS(desc,"B9",buf);    /* szName */
  2111.     if (uLevel == 1) {
  2112.       PACKS(desc,"B21","");    /* szUserName */
  2113.       PACKI(desc,"W",0);        /* uJobId */
  2114.       PACKI(desc,"W",0);        /* fsStatus */
  2115.       PACKS(desc,"z","");    /* pszStatus */
  2116.       PACKI(desc,"W",0);        /* time */
  2117.     }
  2118.   }
  2119.   if (uLevel == 2 || uLevel == 3) {
  2120.     PACKS(desc,"z",buf);        /* pszPrinterName */
  2121.     if (uLevel == 3) {
  2122.       PACKS(desc,"z","");    /* pszUserName */
  2123.       PACKS(desc,"z","");    /* pszLogAddr */
  2124.       PACKI(desc,"W",0);        /* uJobId */
  2125.       PACKI(desc,"W",0);        /* fsStatus */
  2126.       PACKS(desc,"z","");    /* pszStatus */
  2127.       PACKS(desc,"z","");    /* pszComment */
  2128.       PACKS(desc,"z","NULL"); /* pszDrivers */
  2129.       PACKI(desc,"W",0);        /* time */
  2130.       PACKI(desc,"W",0);        /* pad1 */
  2131.     }
  2132.   }
  2133. }
  2134.  
  2135. static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
  2136.                   int mdrcnt,int mprcnt,
  2137.                   char **rdata,char **rparam,
  2138.                   int *rdata_len,int *rparam_len)
  2139. {
  2140.   char *str1 = param+2;
  2141.   char *str2 = skip_string(str1,1);
  2142.   char *p = skip_string(str2,1);
  2143.   char* PrinterName = p;
  2144.   int uLevel,cbBuf;
  2145.   struct pack_desc desc;
  2146.   int snum;
  2147.  
  2148.   bzero(&desc,sizeof(desc));
  2149.  
  2150.   p = skip_string(p,1);
  2151.   uLevel = SVAL(p,0);
  2152.   cbBuf = SVAL(p,2);
  2153.  
  2154.   DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
  2155.  
  2156.   /* check it's a supported varient */
  2157.   if (strcmp(str1,"zWrLh") != 0) return False;
  2158.   if (!check_printdest_info(&desc,uLevel,str2)) return False;
  2159.  
  2160.   snum = lp_servicenumber(PrinterName);
  2161.   if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
  2162.     int pnum = lp_servicenumber(PRINTERS_NAME);
  2163.     if (pnum >= 0) {
  2164.       lp_add_printer(PrinterName,pnum);
  2165.       snum = lp_servicenumber(PrinterName);
  2166.     }
  2167.   }
  2168.  
  2169.   if (snum < 0) {
  2170.     *rdata_len = 0;
  2171.     desc.errcode = NERR_DestNotFound;
  2172.     desc.neededlen = 0;
  2173.   }
  2174.   else {
  2175.     if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
  2176.     desc.base = *rdata;
  2177.     desc.buflen = mdrcnt;
  2178.     if (init_package(&desc,1,0)) {
  2179.       fill_printdest_info(cnum,snum,uLevel,&desc);
  2180.     }
  2181.     *rdata_len = desc.usedlen;
  2182.   }
  2183.  
  2184.   *rparam_len = 6;
  2185.   *rparam = REALLOC(*rparam,*rparam_len);
  2186.   SSVALS(*rparam,0,desc.errcode);
  2187.   SSVAL(*rparam,2,0);
  2188.   SSVAL(*rparam,4,desc.neededlen);
  2189.  
  2190.   DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
  2191.   return(True);
  2192. }
  2193.  
  2194. static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
  2195.                    int mdrcnt,int mprcnt,
  2196.                    char **rdata,char **rparam,
  2197.                    int *rdata_len,int *rparam_len)
  2198. {
  2199.   char *str1 = param+2;
  2200.   char *str2 = skip_string(str1,1);
  2201.   char *p = skip_string(str2,1);
  2202.   int uLevel,cbBuf;
  2203.   int queuecnt;
  2204.   int i, n, succnt=0;
  2205.   struct pack_desc desc;
  2206.   int services = lp_numservices();
  2207.  
  2208.   bzero(&desc,sizeof(desc));
  2209.  
  2210.   uLevel = SVAL(p,0);
  2211.   cbBuf = SVAL(p,2);
  2212.  
  2213.   DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
  2214.  
  2215.   /* check it's a supported varient */
  2216.   if (strcmp(str1,"WrLeh") != 0) return False;
  2217.   if (!check_printdest_info(&desc,uLevel,str2)) return False;
  2218.  
  2219.   queuecnt = 0;
  2220.   for (i = 0; i < services; i++)
  2221.     if (lp_print_ok(i) && lp_browseable(i))
  2222.       queuecnt++;
  2223.  
  2224.   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
  2225.   desc.base = *rdata;
  2226.   desc.buflen = mdrcnt;
  2227.   if (init_package(&desc,queuecnt,0)) {    
  2228.     succnt = 0;
  2229.     n = 0;
  2230.     for (i = 0; i < services; i++) {
  2231.       if (lp_print_ok(i) && lp_browseable(i)) {
  2232.     fill_printdest_info(cnum,i,uLevel,&desc);
  2233.     n++;
  2234.     if (desc.errcode == NERR_Success) succnt = n;
  2235.       }
  2236.     }
  2237.   }
  2238.  
  2239.   *rdata_len = desc.usedlen;
  2240.  
  2241.   *rparam_len = 8;
  2242.   *rparam = REALLOC(*rparam,*rparam_len);
  2243.   SSVALS(*rparam,0,desc.errcode);
  2244.   SSVAL(*rparam,2,0);
  2245.   SSVAL(*rparam,4,succnt);
  2246.   SSVAL(*rparam,6,queuecnt);
  2247.  
  2248.   DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
  2249.   return(True);
  2250. }
  2251.  
  2252. static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
  2253.                  int mdrcnt,int mprcnt,
  2254.                  char **rdata,char **rparam,
  2255.                  int *rdata_len,int *rparam_len)
  2256. {
  2257.   char *str1 = param+2;
  2258.   char *str2 = skip_string(str1,1);
  2259.   char *p = skip_string(str2,1);
  2260.   int uLevel,cbBuf;
  2261.   int succnt;
  2262.   struct pack_desc desc;
  2263.  
  2264.   bzero(&desc,sizeof(desc));
  2265.  
  2266.   uLevel = SVAL(p,0);
  2267.   cbBuf = SVAL(p,2);
  2268.  
  2269.   DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
  2270.  
  2271.   /* check it's a supported varient */
  2272.   if (strcmp(str1,"WrLeh") != 0) return False;
  2273.   if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
  2274.  
  2275.   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
  2276.   desc.base = *rdata;
  2277.   desc.buflen = mdrcnt;
  2278.   if (init_package(&desc,1,0)) {
  2279.     PACKS(&desc,"B41","NULL");
  2280.   }
  2281.  
  2282.   succnt = (desc.errcode == NERR_Success ? 1 : 0);
  2283.  
  2284.   *rdata_len = desc.usedlen;
  2285.  
  2286.   *rparam_len = 8;
  2287.   *rparam = REALLOC(*rparam,*rparam_len);
  2288.   SSVALS(*rparam,0,desc.errcode);
  2289.   SSVAL(*rparam,2,0);
  2290.   SSVAL(*rparam,4,succnt);
  2291.   SSVAL(*rparam,6,1);
  2292.  
  2293.   DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
  2294.   return(True);
  2295. }
  2296.  
  2297. static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data,
  2298.                 int mdrcnt,int mprcnt,
  2299.                 char **rdata,char **rparam,
  2300.                 int *rdata_len,int *rparam_len)
  2301. {
  2302.   char *str1 = param+2;
  2303.   char *str2 = skip_string(str1,1);
  2304.   char *p = skip_string(str2,1);
  2305.   int uLevel,cbBuf;
  2306.   int succnt;
  2307.   struct pack_desc desc;
  2308.  
  2309.   bzero(&desc,sizeof(desc));
  2310.  
  2311.   uLevel = SVAL(p,0);
  2312.   cbBuf = SVAL(p,2);
  2313.  
  2314.   DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
  2315.  
  2316.   /* check it's a supported varient */
  2317.   if (strcmp(str1,"WrLeh") != 0) return False;
  2318.   if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
  2319.  
  2320.   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
  2321.   desc.base = *rdata;
  2322.   desc.buflen = mdrcnt;
  2323.   desc.format = str2;
  2324.   if (init_package(&desc,1,0)) {
  2325.     PACKS(&desc,"B13","lpd");
  2326.   }
  2327.  
  2328.   succnt = (desc.errcode == NERR_Success ? 1 : 0);
  2329.  
  2330.   *rdata_len = desc.usedlen;
  2331.  
  2332.   *rparam_len = 8;
  2333.   *rparam = REALLOC(*rparam,*rparam_len);
  2334.   SSVALS(*rparam,0,desc.errcode);
  2335.   SSVAL(*rparam,2,0);
  2336.   SSVAL(*rparam,4,succnt);
  2337.   SSVAL(*rparam,6,1);
  2338.  
  2339.   DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
  2340.   return(True);
  2341. }
  2342.  
  2343. static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
  2344.                    int mdrcnt,int mprcnt,
  2345.                    char **rdata,char **rparam,
  2346.                    int *rdata_len,int *rparam_len)
  2347. {
  2348.   char *str1 = param+2;
  2349.   char *str2 = skip_string(str1,1);
  2350.   char *p = skip_string(str2,1);
  2351.   int uLevel,cbBuf;
  2352.   int succnt;
  2353.   struct pack_desc desc;
  2354.  
  2355.   bzero(&desc,sizeof(desc));
  2356.  
  2357.   uLevel = SVAL(p,0);
  2358.   cbBuf = SVAL(p,2);
  2359.  
  2360.   DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
  2361.  
  2362.   /* check it's a supported varient */
  2363.   if (strcmp(str1,"WrLeh") != 0) return False;
  2364.   if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
  2365.  
  2366.   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
  2367.   bzero(&desc,sizeof(desc));
  2368.   desc.base = *rdata;
  2369.   desc.buflen = mdrcnt;
  2370.   desc.format = str2;
  2371.   if (init_package(&desc,1,0)) {
  2372.     PACKS(&desc,"B13","lp0");
  2373.   }
  2374.  
  2375.   succnt = (desc.errcode == NERR_Success ? 1 : 0);
  2376.  
  2377.   *rdata_len = desc.usedlen;
  2378.  
  2379.   *rparam_len = 8;
  2380.   *rparam = REALLOC(*rparam,*rparam_len);
  2381.   SSVALS(*rparam,0,desc.errcode);
  2382.   SSVAL(*rparam,2,0);
  2383.   SSVAL(*rparam,4,succnt);
  2384.   SSVAL(*rparam,6,1);
  2385.  
  2386.   DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
  2387.   return(True);
  2388. }
  2389.  
  2390. /****************************************************************************
  2391.   the buffer was too small
  2392.   ****************************************************************************/
  2393. static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
  2394.              int mdrcnt,int mprcnt,
  2395.              char **rdata,char **rparam,
  2396.              int *rdata_len,int *rparam_len)
  2397. {
  2398.   *rparam_len = MIN(*rparam_len,mprcnt);
  2399.   *rparam = REALLOC(*rparam,*rparam_len);
  2400.  
  2401.   *rdata_len = 0;
  2402.  
  2403.   SSVAL(*rparam,0,NERR_BufTooSmall);
  2404.  
  2405.   DEBUG(3,("Supplied buffer too small in API command\n"));
  2406.  
  2407.   return(True);
  2408. }
  2409.  
  2410.  
  2411. /****************************************************************************
  2412.   the request is not supported
  2413.   ****************************************************************************/
  2414. static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
  2415.                 int mdrcnt,int mprcnt,
  2416.                 char **rdata,char **rparam,
  2417.                 int *rdata_len,int *rparam_len)
  2418. {
  2419.   *rparam_len = 4;
  2420.   *rparam = REALLOC(*rparam,*rparam_len);
  2421.  
  2422.   *rdata_len = 0;
  2423.  
  2424.   SSVAL(*rparam,0,NERR_notsupported);
  2425.   SSVAL(*rparam,2,0);        /* converter word */
  2426.  
  2427.   DEBUG(3,("Unsupported API command\n"));
  2428.  
  2429.   return(True);
  2430. }
  2431.  
  2432.  
  2433.  
  2434.  
  2435. struct
  2436. {
  2437.   char *name;
  2438.   int id;
  2439.   BOOL (*fn)();
  2440.   int flags;
  2441. } api_commands[] = {
  2442.   {"RNetShareEnum",    0,    api_RNetShareEnum,0},
  2443.   {"RNetShareGetInfo",    1,    api_RNetShareGetInfo,0},
  2444.   {"RNetServerGetInfo",    13,    api_RNetServerGetInfo,0},
  2445.   {"RNetUserGetInfo",    56,    api_RNetUserGetInfo,0},
  2446.   {"NetUserGetGroups",    59,    api_NetUserGetGroups,0},
  2447.   {"NetWkstaGetInfo",    63,    api_NetWkstaGetInfo,0},
  2448.   {"DosPrintQEnum",    69,    api_DosPrintQEnum,0},
  2449.   {"DosPrintQGetInfo",    70,    api_DosPrintQGetInfo,0},
  2450.   {"WPrintJobEnumerate",76,    api_WPrintJobEnumerate,0},
  2451.   {"WPrintJobGetInfo",    77,    api_WPrintJobGetInfo,0},
  2452.   {"RDosPrintJobDel",    81,    api_RDosPrintJobDel,0},
  2453.   {"RDosPrintJobPause",    82,    api_RDosPrintJobDel,0},
  2454.   {"RDosPrintJobResume",83,    api_RDosPrintJobDel,0},
  2455.   {"WPrintDestEnum",    84,    api_WPrintDestEnum,0},
  2456.   {"WPrintDestGetInfo",    85,    api_WPrintDestGetInfo,0},
  2457.   {"NetRemoteTOD",    91,    api_NetRemoteTOD,0},
  2458.   {"WPrintQueuePurge",    103,    api_WPrintQueuePurge,0},
  2459.   {"NetServerEnum",    104,    api_RNetServerEnum,0},
  2460.   {"WAccessGetUserPerms",105,    api_WAccessGetUserPerms,0},
  2461.   {"SetUserPassword",    115,    api_SetUserPassword,0},
  2462.   {"WWkstaUserLogon",    132,    api_WWkstaUserLogon,0},
  2463.   {"PrintJobInfo",    147,    api_PrintJobInfo,0},
  2464.   {"WPrintDriverEnum",    205,    api_WPrintDriverEnum,0},
  2465.   {"WPrintQProcEnum",    206,    api_WPrintQProcEnum,0},
  2466.   {"WPrintPortEnum",    207,    api_WPrintPortEnum,0},
  2467.   {NULL,        -1,    api_Unsupported,0}};
  2468.  
  2469.  
  2470. /****************************************************************************
  2471.   handle remote api calls
  2472.   ****************************************************************************/
  2473. static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
  2474.              int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
  2475. {
  2476.   int api_command = SVAL(params,0);
  2477.   char *rdata = NULL;
  2478.   char *rparam = NULL;
  2479.   int rdata_len = 0;
  2480.   int rparam_len = 0;
  2481.   BOOL reply=False;
  2482.   int i;
  2483.  
  2484.   DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
  2485.        api_command,params+2,skip_string(params+2,1),
  2486.        tdscnt,tpscnt,mdrcnt,mprcnt));
  2487.  
  2488.   for (i=0;api_commands[i].name;i++)
  2489.     if (api_commands[i].id == api_command && api_commands[i].fn)
  2490.       {
  2491.     DEBUG(3,("Doing %s\n",api_commands[i].name));
  2492.     break;
  2493.       }
  2494.  
  2495.   rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
  2496.   rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
  2497.  
  2498.   reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
  2499.                  &rdata,&rparam,&rdata_len,&rparam_len);
  2500.  
  2501.  
  2502.   if (rdata_len > mdrcnt ||
  2503.       rparam_len > mprcnt)
  2504.     {
  2505.       reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
  2506.                &rdata,&rparam,&rdata_len,&rparam_len);
  2507.     }
  2508.         
  2509.  
  2510.   /* if we get False back then it's actually unsupported */
  2511.   if (!reply)
  2512.     api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
  2513.             &rdata,&rparam,&rdata_len,&rparam_len);
  2514.  
  2515.       
  2516.  
  2517.   /* now send the reply */
  2518.   send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
  2519.  
  2520.   if (rdata)
  2521.     free(rdata);
  2522.   if (rparam)
  2523.     free(rparam);
  2524.   
  2525.   return(-1);
  2526. }
  2527.  
  2528. /****************************************************************************
  2529.   handle named pipe commands
  2530.   ****************************************************************************/
  2531. static int named_pipe(int cnum,int uid, char *outbuf,char *name,
  2532.               uint16 *setup,char *data,char *params,
  2533.               int suwcnt,int tdscnt,int tpscnt,
  2534.               int msrcnt,int mdrcnt,int mprcnt)
  2535. {
  2536.  
  2537.   if (strequal(name,"LANMAN"))
  2538.     return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
  2539.  
  2540.   DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
  2541.        name,(int)setup[0],(int)setup[1]));
  2542.   
  2543.   return(0);
  2544. }
  2545.  
  2546.  
  2547. /****************************************************************************
  2548.   reply to a SMBtrans
  2549.   ****************************************************************************/
  2550. int reply_trans(char *inbuf,char *outbuf)
  2551. {
  2552.   fstring name;
  2553.  
  2554.   char *data=NULL,*params=NULL;
  2555.   uint16 *setup=NULL;
  2556.  
  2557.   int outsize = 0;
  2558.   int cnum = SVAL(inbuf,smb_tid);
  2559.   int uid = SVAL(inbuf,smb_uid);
  2560.  
  2561.   int tpscnt = SVAL(inbuf,smb_vwv0);
  2562.   int tdscnt = SVAL(inbuf,smb_vwv1);
  2563.   int mprcnt = SVAL(inbuf,smb_vwv2);
  2564.   int mdrcnt = SVAL(inbuf,smb_vwv3);
  2565.   int msrcnt = CVAL(inbuf,smb_vwv4);
  2566.   BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
  2567.   BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
  2568.   int pscnt = SVAL(inbuf,smb_vwv9);
  2569.   int psoff = SVAL(inbuf,smb_vwv10);
  2570.   int dscnt = SVAL(inbuf,smb_vwv11);
  2571.   int dsoff = SVAL(inbuf,smb_vwv12);
  2572.   int suwcnt = CVAL(inbuf,smb_vwv13);
  2573.  
  2574.   StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
  2575.   
  2576.   if (tdscnt)
  2577.     {
  2578.       data = (char *)malloc(tdscnt);
  2579.       memcpy(data,smb_base(inbuf)+dsoff,dscnt);
  2580.     }
  2581.   if (tpscnt)
  2582.     {
  2583.       params = (char *)malloc(tpscnt);
  2584.       memcpy(params,smb_base(inbuf)+psoff,pscnt);
  2585.     }
  2586.  
  2587.   if (suwcnt)
  2588.     {
  2589.       int i;
  2590.       setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
  2591.       for (i=0;i<suwcnt;i++)
  2592.     setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
  2593.     }
  2594.  
  2595.  
  2596.   if (pscnt < tpscnt || dscnt < tdscnt)
  2597.     {
  2598.       /* We need to send an interim response then receive the rest
  2599.      of the parameter/data bytes */
  2600.       outsize = set_message(outbuf,0,0,True);
  2601.       show_msg(outbuf);
  2602.       send_smb(Client,outbuf);
  2603.     }
  2604.  
  2605.   /* receive the rest of the trans packet */
  2606.   while (pscnt < tpscnt || dscnt < tdscnt)
  2607.     {
  2608.       int pcnt,poff,dcnt,doff,pdisp,ddisp;
  2609.  
  2610.       receive_smb(Client,inbuf, 0);
  2611.       show_msg(inbuf);
  2612.       
  2613.       /* Ensure this is still a trans packet (sanity check) */
  2614.       if(CVAL(inbuf, smb_com) != SMBtrans)
  2615.     {
  2616.       DEBUG(2,("Invalid secondary trans2 packet\n"));
  2617.       if (params) free(params);
  2618.       if (data) free(data);
  2619.       if (setup) free(setup);
  2620.       return(ERROR(ERRSRV,ERRerror));
  2621.     }
  2622.       
  2623.       tpscnt = SVAL(inbuf,smb_vwv0);
  2624.       tdscnt = SVAL(inbuf,smb_vwv1);
  2625.  
  2626.       pcnt = SVAL(inbuf,smb_vwv2);
  2627.       poff = SVAL(inbuf,smb_vwv3);
  2628.       pdisp = SVAL(inbuf,smb_vwv4);
  2629.       
  2630.       dcnt = SVAL(inbuf,smb_vwv5);
  2631.       doff = SVAL(inbuf,smb_vwv6);
  2632.       ddisp = SVAL(inbuf,smb_vwv7);
  2633.       
  2634.       pscnt += pcnt;
  2635.       dscnt += dcnt;
  2636.  
  2637.       if (pcnt)
  2638.     memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
  2639.       if (dcnt)
  2640.     memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);      
  2641.     }
  2642.  
  2643.  
  2644.   DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
  2645.   
  2646.  
  2647.   if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
  2648.     outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
  2649.              suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
  2650.  
  2651.  
  2652.   if (data) free(data);
  2653.   if (params) free(params);
  2654.   if (setup) free(setup);
  2655.  
  2656.   if (close_on_completion)
  2657.     close_cnum(cnum,uid);
  2658.  
  2659.   if (one_way)
  2660.     return(-1);
  2661.   
  2662.   if (outsize == 0)
  2663.     return(ERROR(ERRSRV,ERRnosupport));
  2664.  
  2665.   return(outsize);
  2666. }
  2667.  
  2668.  
  2669.